package com.example.endproject;

import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.GridView;
import android.widget.ListAdapter;
import android.widget.SimpleAdapter;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;

public class Game2048Activity extends Activity {
    private static final String TAG = "Game2048Activity";
    Item[][] items;//每个区块的值
    boolean isAdd = true;//是否可加
    boolean hasInit = false;
    GridView gridView;
    TextView scoreView;
    int score = 0;
    SimpleAdapter listAdapter;
    ArrayList<HashMap<String,String>> list;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_game2048);
        gridView = findViewById(R.id.gameScreen);
        scoreView = findViewById(R.id.score);
        init();
        paint();
        onTouchListen();
    }

    public void init(){//对items进行初始化,随机两个位置放2和4
        items = new Item[4][4];
        for (int i =0;i<4;i++){
            for(int j =0;j<4;j++){
                items[i][j] = new Item();
            }
        }
        isAdd = true;
        createRandom();
        isAdd = true;
        createRandom();

    }

    @SuppressLint("ClickableViewAccessibility")
    public void onTouchListen(){
        final float[] startX = new float[1];
        final float[] startY = new float[1];
        final float[] offsetX = new float[1];
        final float[] offsetY = new float[1];
        gridView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {

                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN://按下
                        //Log.i(TAG, "onTouch: down");
                        startX[0] = event.getX();
                        startY[0] = event.getY();
                        break;
                    case MotionEvent.ACTION_UP://抬起
                        //Log.i(TAG, "onTouch: up");
                        offsetX[0] = event.getX();
                        offsetY[0] = event.getY();

                        if (Math.abs(offsetX[0]-startX[0]) > Math.abs(offsetY[0]-startY[0])) { // 加此判断是为了解决当用户向斜方向滑动时程序应如何判断的问题

                            if (offsetX[0] - startX[0] < 0f) {
                                Log.i(TAG, "onTouch: left");
                                moveLeft();
                                createRandom();
                                paint();

                            } else if (offsetX[0] - startX[0] > 0f) {
                                Log.i(TAG, "onTouch: right");
                                moveRight();
                                createRandom();
                                paint();
                            }

                        } else { // 判断向上向下

                            if (offsetY[0] - startY[0] < 0f) {
                                Log.i(TAG, "onTouch: up");
                                moveUp();
                                createRandom();
                                paint();

                            } else if (offsetY[0] - startY[0] > 0f) {
                                Log.i(TAG, "onTouch: down");
                                moveDown();
                                createRandom();
                                paint();

//                                Log.i(TAG, "onTouch: sx="+ startX[0]);
//                                Log.i(TAG, "onTouch: sy="+ startY[0]);
//                                Log.i(TAG, "onTouch: ex="+ offsetX[0]);
//                                Log.i(TAG, "onTouch: ey="+ offsetY[0]);
                            }

                        }
                        break;
                }
                return true; // 此处必须返回true
            }
        });
    }

    public void createRandom(){//随机在空白处增加一个值
        ArrayList<Item> list = getEmpty();//获取空白的值
        if (isAdd && !list.isEmpty()){//可以增加且空白元素不为空
            Random random = new Random();
            int index = random.nextInt(list.size());
            Item item =  list.get(index);
            item.setVal((random.nextInt(4)%3 == 0)? 2:4);//百分之25%的概率置放4,75%的概率置放2
            isAdd = false;
        }
    }

    public ArrayList<Item> getEmpty(){//获取空白的元素
        ArrayList<Item> list = new ArrayList<>();
        for(int i =0;i<4;i++){
            for(int j =0;j<4;j++){
                if (items[i][j].val == 0){
                    list.add(items[i][j]);
                }
            }
        }
        return list;
    }

    private boolean moveLeft() {
        for (int i = 0; i < 4; i++) {
            for (int j = 1, index = 0; j < 4; j++) {
                if (items[i][j].val > 0) {
                    if (items[i][j].val == items[i][index].val) {
                        score += items[i][index++].val <<= 1;//加两倍的分
                        items[i][j].val = 0;
                        isAdd = true;
                    } else if (items[i][index].val == 0) {
                        items[i][index].val = items[i][j].val;
                        items[i][j].val = 0;
                        isAdd = true;
                    } else if (items[i][++index].val == 0) {
                        items[i][index].val = items[i][j].val;
                        items[i][j].val = 0;
                        isAdd = true;
                    }
                }
            }
        }
        return isAdd;
    }

    private boolean moveRight() {
        for (int i = 0; i < 4; i++) {
            for (int j = 2, index = 3; j >= 0; j--) {
                if (items[i][j].val > 0) {
                    if (items[i][j].val == items[i][index].val) {
                        score += items[i][index--].val <<= 1;
                        items[i][j].val = 0;
                        isAdd = true;
                    } else if (items[i][index].val == 0) {
                        items[i][index].val = items[i][j].val;
                        items[i][j].val = 0;
                        isAdd = true;
                    } else if (items[i][--index].val == 0) {
                        items[i][index].val = items[i][j].val;
                        items[i][j].val = 0;
                        isAdd = true;
                    }
                }
            }
        }

        return isAdd;
    }

    private boolean moveUp() {
        for (int i = 0; i < 4; i++) {
            for (int j = 1, index = 0; j < 4; j++) {
                if (items[j][i].val > 0) {
                    if (items[j][i].val == items[index][i].val) {
                        score += items[index++][i].val <<= 1;
                        items[j][i].val = 0;
                        isAdd = true;
                    } else if (items[index][i].val == 0) {
                        items[index][i].val = items[j][i].val;
                        items[j][i].val = 0;
                        isAdd = true;
                    } else if (items[++index][i].val == 0){
                        items[index][i].val = items[j][i].val;
                        items[j][i].val = 0;
                        isAdd = true;
                    }
                }
            }
        }

        return isAdd;
    }

    private boolean moveDown() {
        for (int i = 0; i < 4; i++) {
            for (int j = 2, index = 3; j >= 0; j--) {
                if (items[j][i].val > 0) {
                    if (items[j][i].val == items[index][i].val) {
                        score += items[index--][i].val <<= 1;
                        items[j][i].val = 0;
                        isAdd = true;
                    } else if (items[index][i].val == 0) {
                        items[index][i].val = items[j][i].val;
                        items[j][i].val = 0;
                        isAdd = true;
                    } else if (items[--index][i].val == 0) {
                        items[index][i].val = items[j][i].val;
                        items[j][i].val = 0;
                        isAdd = true;
                    }
                }
            }
        }

        return isAdd;
    }

    private boolean judgeGameOver() {
        if (!getEmpty().isEmpty()) {//有空的格子则能继续游戏
            return false;
        }
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                //判断是否存在可合并的方格
                if (items[i][j].val == items[i][j + 1].val
                        || items[i][j].val == items[i + 1][j].val) {
                    return false;
                }
            }
        }
        for (int i = 0; i<3;i++){
            if (items[3][i].val == items[3][i+1].val || items[i][3].val == items[i+1][3].val)
                return false;
        }
        return true;
    }

    private void paint(){
            if (judgeGameOver()){
                AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setTitle("很遗憾,您已经无路可走了...")
                        .setMessage("您最终的得分为:"+score+"  是否重开?")
                .setPositiveButton("重开", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        init();
                        score=0;
                        paint();
                    }
                })
                .setNegativeButton("否",null);
                builder.create().show();
            }
            if (!hasInit){
                list = new ArrayList<>();
                for (int i = 0;i < 4;i++){
                    for (int j = 0;j < 4;j++){
                        HashMap<String,String> map = new HashMap<>();
                        map.put("val",items[i][j].val+"");
                        list.add(map);
                    }
                }
                listAdapter = new SimpleAdapter(this,list,R.layout.itemsquare,new String[]{"val"},new int[]{R.id.square});
                gridView.setAdapter(listAdapter);
                hasInit = true;
            }
            else {
                int count = 0;
                for (int i = 0;i < 4;i++){
                    for (int j = 0;j < 4;j++){
                        HashMap<String,String> map = new HashMap<>();
                        map.put("val",items[i][j].val+"");
                        list.set(count++,map);
                    }
                }
                listAdapter.notifyDataSetChanged();
                scoreView.setText(score+"");
            }
    }

    public void retry(View view){
        init();
        score=0;
        paint();
    }
}